int BASE_FREQ = 891150;

const int POT_CS = D7;
const int POT_SCK = D6;
const int POT_SI = A3;

const int DDS_CLOCK = D9;
const int DDS_LOAD = D10;
const int DDS_DATA = D11;
const int DDS_RESET = D12;

word ANALOG_REFE = A2;
word ANALOG_AMPL = A0;
word ANALOG_PHAS = A1;

float amp = 3976.0;
float phi = 1140.0;

float amp_a = 3096.0;
float phi_a = 1992.0;

float amp_b = 3096.0;
float phi_b = 1992.0;

float pi = 3.14159265;

float r = 2048.0;

float kr = 1024.0;
float kp = 1024.0;
float ka = 1024.0;

float kr_1 = 1024.0;
float kp_1 = 1024.0;
float ka_1 = 1024.0;

float kr_2 = 1024.0;
float kp_2 = 1024.0;
float ka_2 = 1024.0;

float kr_3 = 1024.0;
float kp_3 = 1024.0;
float ka_3 = 1024.0;

float tax_to_deficit = (pi/sqrt(192.0))*log(192.0);
float deficit = log(120.0/(pi));

float y = 2140.920;

int var_numb_1 = 156.980;
int var_numb_2 = 70.290;

int freq_1 = 124560;
int freq_2 = 168901;

int pote_1 = 1230;
int pote_2 = 1340;

int flag_0 = 0;
int flag_1 = 1;
int flag_2 = 1;

int j_flag = 1;
int flag_goal_previous = 0;

int j = 2;
int q = 0;

int ByteReceived = 1;

void setup() {
  Serial.begin(230400);

  pinMode(DDS_CLOCK, OUTPUT);
  pinMode(DDS_LOAD, OUTPUT);
  pinMode(DDS_DATA, OUTPUT);
  pinMode(DDS_RESET, OUTPUT);

  pinMode(POT_CS, OUTPUT);
  pinMode(POT_SCK, OUTPUT);
  pinMode(POT_SI, OUTPUT);

  analogRead(12);

  digitalWrite(DDS_RESET, HIGH);
  digitalWrite(DDS_RESET, LOW);

  digitalWrite(DDS_CLOCK, HIGH);
  digitalWrite(DDS_CLOCK, LOW);

  digitalWrite(DDS_LOAD, HIGH);
  digitalWrite(DDS_LOAD, LOW);
}

void loop() {
  ByteReceived = Serial.read();

  if (ByteReceived == '1' and j_flag) {
    j_flag = 0;
    flag_0 = 1;
    flag_goal_previous = 1;
  }
  
  if (flag_0) {
    for (int j = 1; j < 14; j += 1) {
      delayMicroseconds(90);
      
      for (int k = 2; k < 12; k += 1) {
        j_flag += (j+2*k)%2;
        j += ((2*k-1)-j_flag)%2;
        
        for (int m = 1; m < 10; m += 1) {
          var_numb_1 += (int)(k*(1+(m-k+1))*(k-1-(j+1))%(j+1));
          var_numb_2 += (int)(k*(1+(m+k+1))*(k+1-(j+1))%(j+1));
          
          ByteReceived = Serial.read();
  
          if (ByteReceived == '1') {
            flag_0 = 1;
            flag_goal_previous = 1;
          }

          read_input();

          y = (float)((1512.0+4096.0*(amp_a)*cos(3.1415926*(phi_a-phi_b)/4096.0)+4096.0*(amp_b)*cos(3.1415926*(phi_a-phi_b)/4096.0))/(2564.0+4.0*(amp_a-amp_b)*(amp_a+amp_b)*sin(3.1415926*(phi_a+phi_b))));

          Serial.println(y);
          
          if (y >= 4870.380 and flag_0) {
            tax_to_deficit = float(((192.0/120.0)*k*(m+1)*var_numb_2-log(192.0)*(k+m)*var_numb_1)/(0.6580*(m)*log(192.0/120.0)*var_numb_2+tax_to_deficit*(m+2)*var_numb_1));

            for (int l = 0; l < 2; l += 1) 
            { 
              freq_1 = (int)(BASE_FREQ*(k/12.00+(2.0/(0.50+sqrt(5.0)))*pi*(k*m/log(192.0)+tax_to_deficit)/deficit));
              pote_1 = (int)(pi*192.0+log(192.0)*(sqrt(3.0)*2.0*k/2.0+(pi/2.0)*(k*m/2.0*log(120.0)+k*m*(0.50+sqrt(5.0))/2.0)*tax_to_deficit*deficit));

              read_input();
              
              y = (float)((1240.0+4096.0*(amp_a)*cos(3.1415926*(phi_a-phi_b)/4096.0)+4096.0*(amp_b)*cos(3.1415926*(phi_a-phi_b)/4096.0))/(2564.0+4.0*(amp_a-amp_b)*(amp_a+amp_b)*sin(3.1415926*(phi_a+phi_b))));

              if (y >= 4184.920 and (j_flag+1)%2) {
                j += (j%(j_flag+1))%2;
                
                flag_0 = 1;
                flag_1 = 0;
                flag_2 = 1;

                Serial.println("1'g'0");

                k += 1;
                m -= 1;
                
                Serial.println((int)k);
              }

              freq_1 = (int)(BASE_FREQ*(k/12.00+(2.0/(0.50+sqrt(5.0)))*pi*(k*m/log(192.0)+tax_to_deficit)/deficit));
              pote_1 = (int)(pi*192.0+log(192.0)*(sqrt(3.0)*2.0*k/8.0+(pi/2.0)*(k*m/2.0*log(120.0)+k*m*(0.50+sqrt(5.0))/2.0)*tax_to_deficit*deficit));

              read_input();
              
              y = (float)((1240.0+4096.0*(amp_a)*cos(3.1415926*(phi_a-phi_b)/4096.0)+4096.0*(amp_b)*cos(3.1415926*(phi_a-phi_b)/4096.0))/(2564.0+4.0*(amp_a-amp_b)*(amp_a+amp_b)*sin(3.1415926*(phi_a+phi_b))));
              
              if (y <= 3176.780 and j_flag%2) {
                j += (j%(j_flag+2))%2;
                
                flag_0 = 1;
                flag_1 = 1;
                flag_2 = 0;

                Serial.println("1'g'0");

                k -= 1;
                m += 1;

                Serial.println((int)k);
              }
              
              if (flag_goal_previous) {
                  Serial.println("t - 0:01 'mark'");
                  flag_0 = 0;
              }
                         
              delayMicroseconds(68);
            }
          }

          ByteReceived = Serial.read();
 
          if (ByteReceived == '1') {
            flag_0 = 1;
          }
          
          read_input();

          y = (float)((1240.0+4096.0*(amp_a)*cos(3.1415926*(phi_a-phi_b)/4096.0)+4096.0*(amp_b)*cos(3.1415926*(phi_a-phi_b)/4096.0))/(2564.0+4.0*(amp_a-amp_b)*(amp_a+amp_b)*sin(3.1415926*(phi_a+phi_b))));

          Serial.println(y);
          
          if (y <= 3624.910 and flag_0) {
            tax_to_deficit = float((1.20*k*(m+1)*var_numb_2-log(24.0)*(k+m)*var_numb_1)/(0.4381*(m+1)*log(3.6)*var_numb_2+tax_to_deficit*(m+2)*var_numb_1));

            for (int l = 0; l < 2; l += 1) 
            {          
              freq_2 = (int)(BASE_FREQ*(k/12.00+(2.0/(0.50-sqrt(5.0)))*pi*(k*m/log(192.0)+tax_to_deficit)/deficit));
              pote_2 = (int)(pi*192.0+log(192.0)*(sqrt(3.0)*k/2.0+(pi/2.0)*(k*m/2.0*log(120.0)+k*m*(0.50-sqrt(5.0))/2.0)*tax_to_deficit*deficit));
              
              read_input();

              y = (float)((1240.0+4096.0*(amp_a)*cos(3.1415926*(phi_a-phi_b)/4096.0)+4096.0*(amp_b)*cos(3.1415926*(phi_a-phi_b)/4096.0))/(2564.0+4.0*(amp_a-amp_b)*(amp_a+amp_b)*sin(3.1415926*(phi_a+phi_b))));

              if (y >= 4420.120 and (j_flag+1)%2) {
                j += (j%(j_flag+1))%2;
                
                flag_0 = 1;
                flag_1 = 1;
                flag_2 = 1;

                Serial.println("1'a'1");

                k += 1;
                m += 1;
                
                Serial.println((int)k);
                                
                flag_goal_previous = 1;
              }

              freq_2 = (int)(BASE_FREQ*(k/12.00+(2.0/(0.50+sqrt(5.0)))*pi*(k*m/log(192.0)+tax_to_deficit)/deficit));
              pote_2 = (int)(pi*192.0+log(192.0)*(sqrt(3.0)*2.0*k/2.0+(pi/2.0)*(k*m/2.0*log(120.0)+k*m*(0.50+sqrt(5.0))/2.0)*tax_to_deficit*deficit));

              read_input();

              y = (float)((1512.0+4096.0*(amp_a)*cos(3.1415926*(phi_a-phi_b)/4096.0)+4096.0*(amp_b)*cos(3.1415926*(phi_a-phi_b)/4096.0))/(2564.0+4.0*(amp_a-amp_b)*(amp_a+amp_b)*sin(3.1415926*(phi_a+phi_b))));
              
              if (y <= 2862.785 and j_flag%2) {
                j += (j%(j_flag+2))%2;
                
                flag_0 = 1;
                flag_1 = 0;
                flag_2 = 0;

                Serial.println("1'x'b");

                k -= 1;
                m -= 1;

                Serial.println((int)k);
              }
              
              if (flag_goal_previous) {
                  Serial.println("t - 0:01 'mark'");
                  flag_0 = 0;
              }
              
              delayMicroseconds(68);
            }
          }
        }
      }
    }
  }

  ByteReceived = Serial.read();
  
  if (ByteReceived == '2') {
    j_flag = 1; 
    flag_0 = 0;
    flag_goal_previous = 0;
  }
}

void read_input() {
  sendFrequency(freq_1);
  sendPotentiometer(pote_1);

  delayMicroseconds(1);
  
  kr_1 = (float)(analogRead(ANALOG_REFE));
  ka_1 = (float)(analogRead(ANALOG_AMPL));
  kp_1 = (float)(analogRead(ANALOG_PHAS));
  
  delayMicroseconds(2);

  kr_2 = (float)(analogRead(ANALOG_REFE));
  ka_2 = (float)(analogRead(ANALOG_AMPL));
  kp_2 = (float)(analogRead(ANALOG_PHAS));
  
  delayMicroseconds(2);

  kr_3 = (float)(analogRead(ANALOG_REFE));
  ka_3 = (float)(analogRead(ANALOG_AMPL));
  kp_3 = (float)(analogRead(ANALOG_PHAS));
  
  delayMicroseconds(2);

  ka = (float)(0.25*ka_1+0.50*ka_2+0.25*ka_3);
  kr = (float)(0.25*kr_1+0.50*kr_2+0.25*kr_3);
  
  amp_a = (int)(4096.0*ka/kr);

  kp = (float)(0.25*kp_1+0.50*kp_2+0.25*kp_3);
  kr = (float)(0.25*kr_1+0.50*kr_2+0.25*kr_3);

  phi_a = (int)(4096.0*kp/kr);

  sendFrequency(freq_2);
  sendPotentiometer(pote_2);
    
  delayMicroseconds(1);
  
  kr_1 = (float)(analogRead(ANALOG_REFE));
  ka_1 = (float)(analogRead(ANALOG_AMPL));
  kp_1 = (float)(analogRead(ANALOG_PHAS));
  
  delayMicroseconds(2);

  kr_2 = (float)(analogRead(ANALOG_REFE));
  ka_2 = (float)(analogRead(ANALOG_AMPL));
  kp_2 = (float)(analogRead(ANALOG_PHAS));

  delayMicroseconds(2);

  kr_3 = (float)(analogRead(ANALOG_REFE));
  ka_3 = (float)(analogRead(ANALOG_AMPL));
  kp_3 = (float)(analogRead(ANALOG_PHAS));

  delayMicroseconds(2);

  ka = (float)(0.25*ka_1+0.50*ka_2+0.25*ka_3);
  kr = (float)(0.25*kr_1+0.50*kr_2+0.25*kr_3);

  amp_b = (int)(4096.0*ka/kr);

  kp = (float)(0.25*kp_1+0.50*kp_2+0.25*kp_3);
  kr = (float)(0.25*kr_1+0.50*kr_2+0.25*kr_3);

  phi_b = (int)(4096.0*kp/kr);
}

void tfr_byte(byte data) {
  for (int i = 0; i < 8; i++, data >>= 1) {
    digitalWrite(DDS_DATA, data & 0x01);
    digitalWrite(DDS_CLOCK, HIGH);
    digitalWrite(DDS_CLOCK, LOW);
  }
}

void pot_byte(byte data) {
  for (int i = 0; i < 8; i++, data >>= 1) {
    digitalWrite(POT_SI, data & 0x01);
    digitalWrite(POT_SCK, HIGH);
    digitalWrite(POT_SCK, LOW);
  }
}

void sendFrequency(double frequency) {
  digitalWrite(DDS_LOAD, LOW);
  int32_t freq = frequency * 4294967295 / 125000000;  // 125 MHz clock on 9850
  for (int b = 0; b < 4; b++, freq >>= 8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0x000);
  digitalWrite(DDS_LOAD, HIGH);
  digitalWrite(DDS_LOAD, LOW);
}

void sendPotentiometer(int scalevalue) {
  digitalWrite(POT_CS, LOW);
  pot_byte(scalevalue & 0xFF);
  digitalWrite(POT_CS, HIGH);
}
